﻿using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Animations;
using Asset;

/// <summary>
/// 2D animation没有Avtar  无法使用Playable播放动画
/// 
/// </summary>
namespace AnimPlayable
{
    public class AnimState
    {
        public string animName;
        public int port;
        public float animLength;
        private AnimationClip clip;
        public AnimationClip Clip
        {
            get
            {
                return this.clip;
            }
            set
            {
                this.clip = value;
                this.animLength = this.clip.length;
            }
        }
        public Anim_Mode mode = Anim_Mode.Loop;
        public float useTime = 0;
        public event Action onStart;
        public event Action onEnd;
        public void reset()
        {
            useTime = 0;
        }
    }

    enum AnimGraphStatus
    {
        UnInit,
        Run,
        Stop,
    }

    public class AnimWidget : IAnim
    {
        //other
        GameObject agent;
        PoolObj agentPoolObj;
        Animator animator;
        //Playable
        PlayableGraph graph;
        AnimationMixerPlayable animationMixer = AnimationMixerPlayable.Null;
        ScriptPlayable<AnimPlaybaleBehavior> blenderPlayable;
        AnimGraphStatus animGraphStatus = AnimGraphStatus.UnInit;

        Dictionary<string, AnimState> clipPool = new Dictionary<string, AnimState>();
        public AnimState currAnimState;
        Queue<string> animQueue = new Queue<string>();
        Anim_Mode queueAnimMode = Anim_Mode.Once;
        public void updateAgent(GameObject obj)
        {
            this.agent = obj;
            init();
        }

        private void init()
        {
            //当更新agent的时候 把上一个agent的资源动态引用置空 todo
            this.agentPoolObj = this.agent.GetComponent<PoolObj>();
            this.animator = this.agent.GetComponent<Animator>();
            graph = PlayableGraph.Create();//创建graph
            var animOutput = AnimationPlayableOutput.Create(graph, "myAnim", this.animator);//创建anim ouput
            animationMixer = AnimationMixerPlayable.Create(graph);//混合playable
            blenderPlayable = ScriptPlayable<AnimPlaybaleBehavior>.Create(graph, 1);//playable behavior
            blenderPlayable.GetBehaviour().animWidget = this;
            graph.Connect(animationMixer, 0, blenderPlayable, 0);
            animOutput.SetSourcePlayable(blenderPlayable, 0);
            blenderPlayable.SetInputWeight(0, 1);
            GraphVisualizerClient.Show(graph, "MyGraph");
            animGraphStatus = AnimGraphStatus.Run;
        }

        public void tick(float frameTime)
        {
            if (animGraphStatus == AnimGraphStatus.Run)
            {
                graph.Evaluate(frameTime);
            }
        }

        public void onAnimEnd()
        {
            if (this.animQueue.Count > 0)
            {
                string anim = this.animQueue.Dequeue();
                Anim_Mode mode = this.animQueue.Count <= 0 ? queueAnimMode : Anim_Mode.Once;
                this.playAnim(anim, mode);
            }
        }

        public int QueueCount
        {
            get
            {
                return this.animQueue.Count;
            }
        }

        public void stop()
        {
            animGraphStatus = AnimGraphStatus.Stop;
        }

        public void resume()
        {
            if (animGraphStatus == AnimGraphStatus.Stop)
                animGraphStatus = AnimGraphStatus.Run;
        }

        //直接播放anim 播放单个动画
        public void playAnim(string animName, Anim_Mode mode)
        {
            if (currAnimState != null)
            {
                if (currAnimState.animName == animName)
                {
                    return;
                }
                else
                {
                    currAnimState.reset();
                }
            }
            //1.加载动画
            AnimState animState = getClip(animName);
            //2.连接动画
            var clipPlayable = AnimationClipPlayable.Create(graph, animState.Clip);
            animationMixer.SetInputCount(1);
            animationMixer.DisconnectInput(0);
            animationMixer.ConnectInput(0, clipPlayable, 0);
            animationMixer.SetInputWeight(0, 1);
            animState.port = 0;
            currAnimState = animState;
            currAnimState.mode = mode;
        }

        public void playAnim(string[] anims, Anim_Mode mode)
        {
            int animsCount = anims.Length;
            if (animsCount > 0)
            {
                Anim_Mode animMode = animsCount <= 1 ? mode : Anim_Mode.Once;
                this.playAnim(anims[0], animMode);
                if (animsCount > 1)
                {
                    this.animQueue.Clear();
                    queueAnimMode = mode;
                    for (int i = 1; i < animsCount; i++)
                    {                        
                        this.animQueue.Enqueue(anims[i]);
                    }                    
                }
            }
        }

        //渐变到anim
        public void crossFade(string animName, Anim_Mode mode)
        {
            if (currAnimState != null)
            {
                if (currAnimState.animName == animName)
                {
                    return;
                }
                else
                {
                    currAnimState.reset();
                }
            }
            //如果mix的count==1 则可以混合
            int count = animationMixer.GetInputCount();
            if (count > 1)
            {
                playAnim(animName, mode);
            }
            else
            {
                //1.加载动画
                AnimState animState = getClip(animName);
                //2.连接动画
                var clipPlayable = AnimationClipPlayable.Create(graph, animState.Clip);
                animationMixer.SetInputCount(2);
                int port = 1;
                animationMixer.ConnectInput(port, clipPlayable, 0);
                animationMixer.SetInputWeight(0, 1);
                animationMixer.SetInputWeight(1, 0);
                animState.port = port;
                currAnimState = animState;
                currAnimState.mode = mode;
            }
        }

        private AnimState getClip(string animName)
        {
            AnimState animState;
            if (!clipPool.TryGetValue(animName, out animState))
            {
                AnimationClip clip = PoolMgr.loadAsset<AnimationClip>(animName);
                animState = new AnimState();
                animState.animName = animName;
                animState.Clip = clip;
                this.agentPoolObj.addDymicRefByAsset(animName);
                clipPool.Add(animName, animState);
            }
            return animState;
        }

        //remove是否提供？如果提供 需要清理资源引用
        //private void removeClip(string animName)
        //{
        //    AnimationClip clip;
        //    if (clipPool.TryGetValue(animName, out clip))
        //    {
        //        clipPool.Remove(animName);                
        //    }
        //}




    }

}
